using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
using Newtonsoft.Json;
using System.Runtime.CompilerServices;
using System.Linq;
using twistmachinev2.Entity;
using twistmachinev2.Repository;
using twistmachinev2.OPCUA;

namespace twistmachinev2
{
    /// <summary>
    /// OPCUA配置根类（用于JSON反序列化）
    /// </summary>
    public class OpcUaConfigRoot
    {
        public string ServerUrl { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
        public List<OpcUaNodeConfig> Nodes { get; set; } = new List<OpcUaNodeConfig>();
    }

    /// <summary>
    /// OPCUA节点配置类
    /// </summary>
    [Serializable]
    public class OpcUaNodeConfig
    {
        /// <summary>
        /// 节点ID
        /// </summary>
        public string NodeId { get; set; }

        /// <summary>
        /// 节点名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 数据类型
        /// </summary>
        public string DataType { get; set; }

        /// <summary>
        /// 是否可读
        /// </summary>
        public bool CanRead { get; set; } = true;

        /// <summary>
        /// 是否可写
        /// </summary>
        public bool CanWrite { get; set; } = false;

        /// <summary>
        /// 是否订阅
        /// </summary>
        public bool IsSubscribed { get; set; } = false;

        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        /// 分组
        /// </summary>
        public string Group { get; set; }

        /// <summary>
        /// 映射的属性名称
        /// </summary>
        public string PropertyName { get; set; }

        /// <summary>
        /// 对象名称
        /// </summary>
        public string ObjectName { get; set; }

        /// <summary>
        /// 访问级别
        /// </summary>
        public string AccessLevel { get; set; } = "Read";

        /// <summary>
        /// 扫描频率（毫秒）
        /// </summary>
        public int ScanRate { get; set; } = 1000;

        public OpcUaNodeConfig()
        {
        }

        public OpcUaNodeConfig(string nodeId, string name, string dataType)
        {
            NodeId = nodeId;
            Name = name;
            DataType = dataType;
        }
    }

    /// <summary>
    /// OPCUA节点配置管理器 - 基于数据库的配置管理
    /// </summary>
    public class OpcUaConfigManager : IDisposable
    {
        private List<OpcUaNodeConfig> nodeConfigs;
        private string configFilePath;
        private string serverUrl;
        private OpcUaConfigService _configService;
        private OPCUARepository _repository;
        private bool _disposed = false;

        public OpcUaConfigManager(string configPath = "opcua_config.json")
        {
            configFilePath = configPath;
            InitializeServices();
            LoadConfig();
        }

        /// <summary>
        /// 初始化服务
        /// </summary>
        private void InitializeServices()
        {
            try
            {
                _repository = new OPCUARepository();
                _configService = new OpcUaConfigService(_repository);

                // 检查是否需要从JSON文件迁移数据
                if (File.Exists(configFilePath) && !_configService.HasAnyConfig())
                {
                    _configService.MigrateFromJsonConfig(configFilePath);
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"初始化配置服务失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 获取所有节点配置
        /// </summary>
        public List<OpcUaNodeConfig> GetAllNodes()
        {
            return new List<OpcUaNodeConfig>(nodeConfigs);
        }

        /// <summary>
        /// 根据节点ID获取配置
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        /// <returns>节点配置</returns>
        public OpcUaNodeConfig GetNodeConfig(string nodeId)
        {
            return nodeConfigs.Find(n => n.NodeId == nodeId);
        }

        /// <summary>
        /// 根据分组获取节点配置
        /// </summary>
        /// <param name="group">分组名称</param>
        /// <returns>节点配置列表</returns>
        public List<OpcUaNodeConfig> GetNodesByGroup(string group)
        {
            return nodeConfigs.FindAll(n => n.Group == group);
        }

        /// <summary>
        /// 添加节点配置
        /// </summary>
        /// <param name="nodeConfig">节点配置</param>
        public void AddNode(OpcUaNodeConfig nodeConfig)
        {
            if (nodeConfigs.Exists(n => n.NodeId == nodeConfig.NodeId))
            {
                throw new ArgumentException($"节点ID {nodeConfig.NodeId} 已存在");
            }
            nodeConfigs.Add(nodeConfig);
            var entity = ConvertToEntity(nodeConfig);
            _configService.SaveNodeConfig(entity);
        }

        /// <summary>
        /// 添加节点配置
        /// </summary>
        /// <param name="nodeConfig">节点配置</param>
        public void AddNodeConfig(OpcUaNodeConfig nodeConfig)
        {
            if (nodeConfig != null && !nodeConfigs.Any(n => n.NodeId == nodeConfig.NodeId))
            {
                nodeConfigs.Add(nodeConfig);
                var entity = ConvertToEntity(nodeConfig);
                _configService.SaveNodeConfig(entity);
            }
        }

        /// <summary>
        /// 更新节点配置
        /// </summary>
        /// <param name="nodeConfig">节点配置</param>
        public void UpdateNodeConfig(OpcUaNodeConfig nodeConfig)
        {
            if (nodeConfig != null)
            {
                var existingConfig = nodeConfigs.FirstOrDefault(n => n.NodeId == nodeConfig.NodeId);
                if (existingConfig != null)
                {
                    var index = nodeConfigs.IndexOf(existingConfig);
                    nodeConfigs[index] = nodeConfig;
                    var entity = ConvertToEntity(nodeConfig);
                    _configService.UpdateNodeConfig(entity);
                }
                else
                {
                    AddNodeConfig(nodeConfig);
                }
            }
        }

        /// <summary>
        /// 删除节点配置
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        public void RemoveNodeConfig(string nodeId)
        {
            nodeConfigs.RemoveAll(n => n.NodeId == nodeId);
            var entity = _configService.GetNodeConfigByNodeId(nodeId);
            if (entity != null)
            {
                _configService.DeleteNodeConfig(entity.Id.ToString());
            }
        }

        /// <summary>
        /// 将配置对象转换为实体
        /// </summary>
        private OpcUaNodeConfigEntity ConvertToEntity(OpcUaNodeConfig config)
        {
            return new OpcUaNodeConfigEntity
            {
                NodeId = config.NodeId,
                Name = config.Name,
                Description = config.Description,
                DataType = config.DataType,
                AccessLevel = config.CanWrite ? "ReadWrite" : "Read",
                ScanRate = config.ScanRate,
                IsSubscribed = config.IsSubscribed,
                PropertyName = config.PropertyName,
                ObjectName = config.ObjectName,
                Group = config.Group,
                IsEnabled = true
            };
        }

        /// <summary>
        /// 设置服务器URL
        /// </summary>
        /// <param name="url">服务器URL</param>
        public void SetServerUrl(string url)
        {
            serverUrl = url;
        }

        /// <summary>
        /// 保存配置到数据库
        /// </summary>
        public void SaveConfig()
        {
            try
            {
                // 保存服务器配置
                _configService.SaveServerConfig(serverUrl ?? "opc.tcp://127.0.0.1:49320");

                // 保存节点配置
                var entities = nodeConfigs.Select(ConvertToEntity).ToList();
                _configService.BatchSaveNodeConfigs(entities);
            }
            catch (Exception ex)
            {
                throw new Exception($"保存配置失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed && disposing)
            {
                _configService?.Dispose();
                _repository?.Dispose();
                _disposed = true;
            }
        }

        /// <summary>
        /// 加载配置文件
        /// </summary>
        public void LoadConfig(string configPath = null)
        {
            if (!string.IsNullOrEmpty(configPath))
            {
                configFilePath = configPath;
            }
            LoadConfig();
        }

        public string GetServerUrl()
        {
            return serverUrl ?? GetDefaultServerUrl();

        }

        private string GetDefaultServerUrl()
        {
            return "opc.tcp://127.0.0.1:49320"; // 默认服务器地址，可以根据需要修改
        }

        /// <summary>
        /// 从数据库加载配置
        /// </summary>
        private void LoadConfig()
        {
            try
            {
                // 从数据库加载服务器配置
                var serverConfig = _configService.GetServerConfig();
                serverUrl = serverConfig?.ServerUrl ?? GetDefaultServerUrl();

                // 从数据库加载节点配置
                var nodeConfigEntities = _configService.GetAllNodeConfigs();
                nodeConfigs = ConvertFromEntities(nodeConfigEntities);

                // 如果数据库中没有配置且JSON文件存在，则从JSON文件加载
                if (nodeConfigs.Count == 0 && File.Exists(configFilePath))
                {
                    LoadConfigFromFile();
                }
            }
            catch (Exception ex)
            {
                nodeConfigs = new List<OpcUaNodeConfig>();
                throw new Exception($"加载配置失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 从文件加载配置（备用方法）
        /// </summary>
        private void LoadConfigFromFile()
        {
            try
            {
                if (File.Exists(configFilePath))
                {
                    string extension = Path.GetExtension(configFilePath).ToLower();

                    if (extension == ".json")
                    {
                        // 加载JSON格式配置
                        string jsonContent = File.ReadAllText(configFilePath);
                        OpcUaConfigRoot configRoot = JsonConvert.DeserializeObject<OpcUaConfigRoot>(jsonContent);
                        nodeConfigs = configRoot?.Nodes ?? new List<OpcUaNodeConfig>();
                        serverUrl = configRoot.ServerUrl;//获取服务器地址
                    }
                    else
                    {
                        // 加载XML格式配置
                        XmlSerializer serializer = new XmlSerializer(typeof(List<OpcUaNodeConfig>));
                        using (FileStream fs = new FileStream(configFilePath, FileMode.Open))
                        {
                            nodeConfigs = (List<OpcUaNodeConfig>)serializer.Deserialize(fs) ?? new List<OpcUaNodeConfig>();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"从文件加载配置失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 将实体转换为配置对象
        /// </summary>
        private List<OpcUaNodeConfig> ConvertFromEntities(List<OpcUaNodeConfigEntity> entities)
        {
            var configs = new List<OpcUaNodeConfig>();
            foreach (var entity in entities)
            {
                var config = new OpcUaNodeConfig(entity.NodeId, entity.Name, entity.DataType)
                {
                    Description = entity.Description,
                    Group = entity.Group,
                    PropertyName = entity.PropertyName,
                    ObjectName = entity.ObjectName,
                    CanWrite = entity.AccessLevel?.Contains("Write") == true,
                    IsSubscribed = entity.IsSubscribed
                };
                configs.Add(config);
            }
            return configs;
        }

        /// <summary>
        /// 创建默认配置
        /// </summary>
        private void CreateDefaultConfig()
        {
            nodeConfigs = new List<OpcUaNodeConfig>
            {
                new OpcUaNodeConfig("ns=2;i=1001", "温度传感器1", "Double")
                {
                    Description = "设备温度传感器1",
                    Group = "传感器",
                    PropertyName = "Temperature1",
                    IsSubscribed = true
                },
                new OpcUaNodeConfig("ns=2;i=1002", "压力传感器1", "Double")
                {
                    Description = "设备压力传感器1",
                    Group = "传感器",
                    PropertyName = "Pressure1",
                    IsSubscribed = true
                },
                new OpcUaNodeConfig("ns=2;i=2001", "电机启动", "Boolean")
                {
                    Description = "电机启动控制",
                    Group = "控制",
                    PropertyName = "MotorStart",
                    CanWrite = true
                },
                new OpcUaNodeConfig("ns=2;i=2002", "电机速度", "Int32")
                {
                    Description = "电机速度设定",
                    Group = "控制",
                    PropertyName = "MotorSpeed",
                    CanWrite = true
                }
            };
            SaveConfig();
        }

        /// <summary>
        /// 获取可订阅的节点
        /// </summary>
        /// <returns>可订阅的节点列表</returns>
        public List<OpcUaNodeConfig> GetSubscribableNodes()
        {
            return nodeConfigs.FindAll(n => n.IsSubscribed);
        }

        /// <summary>
        /// 获取可读的节点
        /// </summary>
        /// <returns>可读的节点列表</returns>
        public List<OpcUaNodeConfig> GetReadableNodes()
        {
            return nodeConfigs.FindAll(n => n.CanRead);
        }

        /// <summary>
        /// 获取可写的节点
        /// </summary>
        /// <returns>可写的节点列表</returns>
        public List<OpcUaNodeConfig> GetWritableNodes()
        {
            return nodeConfigs.FindAll(n => n.CanWrite);
        }

        /// <summary>
        /// 根据对象名称获取节点配置
        /// </summary>
        /// <param name="objectName">对象名称</param>
        /// <returns>节点配置列表</returns>
        public List<OpcUaNodeConfig> GetNodesByObject(string objectName)
        {
            return nodeConfigs.FindAll(n => n.ObjectName == objectName);
        }
    }
}